home *** CD-ROM | disk | FTP | other *** search
- ; Low level Gravis Ultrasound interface by Tran (a.k.a. Thomas Pytel)
-
- .386p
- code32 segment para public use32
- assume cs:code32, ds:code32
-
- include pmode.inc
- include low_data.inc
-
- public _gus_data
-
- public voltbl ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DATA
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- align 4
- aclbeg dd 32 dup(?) ; actual channel loop begin |
- aclend dd 32 dup(?) ; actual channel loop end |
- acfreq dw 32 dup(?) ; actual channel frequency value |
- acpan db 32 dup(?) ; actual channel pan position |
- acvol db 32 dup(?) ; actual channel volume (high byte) |
-
- vcacoff db 16 dup(0) ; virtual channel offset in actual
-
- ormgusirqvect dd ? ; old real mode GF1 IRQ vector
-
- freqfactor dw ?, 0 ; frequency calculation factor
-
- gusport102 dw ? ; GUS port + 102h
- gusport103 dw ? ; GUS port + 103h
- gusport104 dw ? ; GUS port + 104h
- gusport107 dw ? ; GUS port + 107h
-
- rmgusirqbuf db 21 dup(?) ; buffer for rm GF1 IRQ callback code
-
- port103val db 43h ; value to set on exit from IRQ
- irqm0tbl dw 0c089h,0a0e6h ; opcodes for IRQ levels (0-7,8-15)
- gusirqvaltbl db 0,0,41h,43h,0,42h,0,44h,0,0,0,45h,46h,0,0,47h
- voltbl db 004h,0a0h,0b0h,0c0h,0c8h,0d0h,0d8h,0e0h
- db 0e4h,0e8h,0ech,0f0h,0f2h,0f4h,0f6h,0f8h
- freqfactortbl dw 44100,38587,34300,30870,28063,25725,23746,22050
- dw 20580,19293
-
- align 4
- _gus_data dd _gus_init, _gus_uninit, _gus_set_bps, _ret
- dd _gus_set_voices, _gus_get_freq, _gus_put_data
- dd _gus_get_data, _ret
- db 00000111b ; info bitmap
- ; bit 0: 0=system RAM, 1=card RAM
- ; bit 1: port needed
- ; bit 2: IRQ number needed
- ; bit 3: DMA number needed
- ; bit 4: Mixing rate selectable
- db 'Gravis Ultrasound',0,'$'
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; CODE
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;-----------------------------------------------------------------------------
- @gusoutb macro index,value
- mov al,&index
- out dx,al
- add dl,2
- mov al,&value
- out dx,al
- sub dl,2
- endm
-
- @gusoutw macro index,value
- mov al,&index
- out dx,al
- inc edx
- mov ax,&value
- out dx,ax
- dec edx
- endm
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; GUS timer IRQ entry
- irq:
- push eax
- mov al,20h
- out 20h,al
- irqm0 dw ? ; out 0a0h,al | mov eax,eax
- sti
- cld
- push ebx ecx edx esi edi ebp ds
- mov ds,cs:_seldata
- mov dx,gusport103 ; reenable GUS timer
- @outb 45h
- add dl,2
- @outb 0
- @outb 8
-
- call _low_rout
-
- ;-----------------------------------------------------------------------------
- mov dx,gusport103
- mov ebp,15
- irql0:
- xor cl,cl
- xchg cl,_low_vccmnd[ebp]
- or cl,cl
- jz irql0c
-
- movzx edi,vcacoff[ebp]
- lea edi,[ebp*2+edi]
-
- test cl,8
- jz short irql0f0
- xor vcacoff[ebp],1
- mov eax,edi
- dec edx
- out dx,al
- inc edx
- mov bl,acvol[edi]
- @gusoutb 7,4
- @gusoutb 8,bl
- @gusoutb 9,bl
- @gusoutb 0dh,40h
- xor edi,1
- or cl,7
- irql0f0:
-
- mov eax,edi
- dec edx
- out dx,al
- inc edx
-
- test cl,4
- jz short irql0f1
- mov bx,_low_vcfreq[ebp*2]
- cmp bx,acfreq[edi*2]
- je short irql0f1
- mov acfreq[edi*2],bx
- @gusoutw 1,bx
- irql0f1:
-
- test cl,2
- jz short irql0f2
- mov bl,_low_vcpan[ebp]
- cmp bl,acpan[edi]
- je short irql0f2
- mov acpan[edi],bl
- @gusoutb 0ch,bl
- irql0f2:
-
- test cl,8
- jz irql0f3
- mov esi,_low_vclbeg[ebp*4]
- cmp esi,aclbeg[edi*4]
- je short irql0f2f0
- mov aclbeg[edi*4],esi
- shrd bx,si,7
- shr esi,7
- @gusoutw 2,si
- @gusoutb 3,bh
- irql0f2f0:
- mov esi,_low_vclend[ebp*4]
- cmp esi,aclend[edi*4]
- je short irql0f2f1
- mov aclend[edi*4],esi
- shrd bx,si,7
- shr esi,7
- @gusoutw 4,si
- @gusoutb 5,bh
- irql0f2f1:
- mov esi,_low_vcsbeg[ebp*4]
- shrd bx,si,7
- shr esi,7
- @gusoutw 0ah,si
- @gusoutb 0bh,bh
- @gusoutb 0,_low_vccntrl[ebp]
- irql0f3:
-
- test cl,1
- jz short irql0f4
- movzx esi,_low_vcvol[ebp]
- shr esi,4
- mov bl,voltbl[esi]
- mov bh,acvol[edi]
- mov ah,bh
- cmp bh,bl
- je short irql0f4
- mov ch,40h
- ja short irql0f3f0
- xchg bl,bh
- xor ch,ch
- irql0f3f0:
- @gusoutb 7,bl
- @gusoutb 8,bh
- @gusoutb 9,ah
- @gusoutb 0dh,ch
- irql0f4:
-
- mov dx,300h
- db 7 dup(0ech) ; in al,dx
- mov dx,gusport103
-
- test cl,1
- jz short irql0f5
- movzx esi,_low_vcvol[ebp]
- shr esi,4
- mov al,voltbl[esi]
- cmp al,ah
- je short irql0f5
- mov acvol[edi],al
- @gusoutb 9,ah
- @gusoutb 0dh,ch
- irql0f5:
-
- test cl,8
- jz short irql0c
- mov esi,_low_vcsbeg[ebp*4]
- shrd bx,si,7
- shr esi,7
- @gusoutw 0ah,si
- @gusoutb 0bh,bh
- @gusoutb 0,_low_vccntrl[ebp]
- xor edi,1
- mov eax,edi
- dec edx
- out dx,al
- inc edx
- mov bl,4
- xchg bl,acvol[edi]
- @gusoutb 9,bl
- @gusoutb 0dh,40h
-
- irql0c:
- sub ebp,1
- jnc irql0
-
- @outb port103val
-
- ;─────────────────────────────────────────────────────────────────────────────
- irqdone:
- pop ds ebp edi esi edx ecx ebx eax
- iretd
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Initialize low level GUS system
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gus_init:
- pushad
- mov ax,900h
- int 31h
- push ax
-
- mov dx,_low_port ; set up all port vars
- @outb 0bh
- add dx,102h
- mov gusport102,dx
- inc edx
- mov gusport103,dx
- inc edx
- mov gusport104,dx
- add dl,3
- mov gusport107,dx
-
- sub dl,4 ; initialize GUS at full voices
- @outb 4ch
- add dl,2
- @outb 0
- mov ecx,10h
- call initr0
- @outb 1
- sub dl,2
- mov ecx,10h
- call initr0
- @gusoutb 41h,0
- @gusoutb 45h,0
- @gusoutb 49h,0
- @outb 0eh
- add dl,2
- @outb 0dfh
- sub dl,3
-
- mov bl,1fh ; set up all voices
- initl0:
- mov al,bl
- and al,7fh
- out dx,al
- inc edx
- @gusoutw 9,0
- @gusoutb 0,0
- @gusoutb 0dh,3
- @gusoutb 6,16
- @outb 0ch
- add dl,2
- @outb 7
- sub dl,3
- mov ecx,1
- call initr0
- xor bl,80h
- js initl0
- sub bl,1
- jnc initl0
-
- sub dx,0f3h ; damn, another undocumented port
- @outb 5
- sub dl,0fh
- @outb 8
- add dl,0bh
- xor al,al
- out dx,al
- add dl,4
- out dx,al
- sub dl,0fh
-
- movzx ebx,_low_irq ; set IRQ channels
- @outb 4bh
- add dl,0bh
- mov al,gusirqvaltbl[ebx]
- out dx,al
- sub dl,0bh
- @outb 9
- add dx,103h
-
- @outb 43h ; how much RAM on the card
- inc edx
- @outw 0ffffh
- dec edx
- @outb 44h
- add dl,2
- xor esi,esi
- mov cl,3
- initl1:
- @outb cl
- add dl,2
- in al,dx
- inc eax
- mov ah,al
- out dx,al
- in al,dx
- sub dl,2
- cmp al,ah
- jne short initl1d
- add esi,40000h
- add cl,4
- test cl,10h
- jz initl1
- initl1d:
- mov _low_ram,esi
- sub dl,2
-
- mov edi,offset aclbeg ; set some beginning values
- mov ecx,80
- mov eax,0ffffffffh
- rep stosd
- mov eax,7070707h
- mov cl,8
- rep stosd
- xor eax,eax
- mov cl,8
- rep stosd
-
- @gusoutb 4ch,3 ; enable GUS normal operation
-
- @gusoutb 47h,0cch ; start GUS timer at 60Hz
- @outb 45h
- add dl,2
- @outb 8
- sub dx,0fdh
- @outb 4
- inc edx
- @outb 2
-
- cmp bl,2 ; set and enable GF1 IRQ (BL=IRQ num)
- jne short $+4
- mov bl,9
- cmp bl,7
- seta al
- movzx eax,al
- mov ax,irqm0tbl[eax*2]
- mov irqm0,ax
- mov edx,offset irq
- call _setirqvect
- mov edi,offset rmgusirqbuf
- call _rmpmirqset
- mov ormgusirqvect,eax
- xor al,al
- call _setirqmask
-
- xor eax,eax ; initial clicks here, not at muz beg
- mov _low_buf,eax
- mov _low_rambase,eax
- mov dword ptr _low_vcvol[0],eax
- mov dword ptr _low_vcvol[4],eax
- mov dword ptr _low_vcvol[8],eax
- mov dword ptr _low_vcvol[12],eax
- mov dword ptr _low_vccntrl[0],eax
- mov dword ptr _low_vccntrl[4],eax
- mov dword ptr _low_vccntrl[8],eax
- mov dword ptr _low_vccntrl[12],eax
- mov edi,offset _low_vcsbeg
- mov ecx,32
- rep stosd
- mov ah,1
- mov ecx,24
- rep stosd
- mov eax,7070707h
- rep stosd
- mov eax,8080808h
- mov dword ptr _low_vccmnd[0],eax
- mov dword ptr _low_vccmnd[4],eax
- mov dword ptr _low_vccmnd[8],eax
- mov dword ptr _low_vccmnd[12],eax
-
- pop ax
- int 31h
- popad
- ret
-
- ;-----------------------------------------------------------------------------
- initr0:
- push ax dx
- mov dx,300h
- initr0l0:
- in al,dx
- in al,dx
- in al,dx
- in al,dx
- in al,dx
- in al,dx
- in al,dx
- loop initr0l0
- pop dx ax
- ret
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Uninitialize low level GUS system
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gus_uninit:
- push eax ebx edx
- mov ax,900h
- int 31h
- push ax
-
- mov bl,_low_irq
- cmp bl,2
- jne short $+4
- mov bl,9
- mov eax,ormgusirqvect
- call _rmpmirqfree
- mov al,1
- call _setirqmask
-
- mov dx,gusport103
- @outb 4ch
- add dl,2
- @outb 0
- sub dx,105h
- @outb 0bh
-
- pop ax
- int 31h
- pop edx ebx eax
- ret
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Set beats per second
- ; In:
- ; AL - beats per second (15-255)
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gus_set_bps:
- push ax bx dx
- movzx bx,al
- mov ax,900h
- int 31h
- push ax
-
- xor dx,dx
- mov ax,3125
- div bx
- mov bl,al
- neg bl
- mov dx,gusport103
- @gusoutb 47h,bl
-
- pop ax
- int 31h
- pop dx bx ax
- ret
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Set number of active voices
- ; In:
- ; AL - number of voices (1-16)
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gus_set_voices:
- push ax edx
- movzx edx,al
- mov ax,900h
- int 31h
- push ax
-
- cmp dl,7
- jae short $+4
- mov dl,7
- shl dl,1
- mov ax,freqfactortbl[edx-14]
- mov freqfactor,ax
- dec edx
- mov ah,dl
- mov dx,gusport103
- @outb 0eh
- add dl,2
- or ah,0c0h
- @outb ah
-
- pop ax
- int 31h
- pop edx ax
- ret
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Convert actual frequency to GUS frequency number
- ; In:
- ; EAX - frequency
- ; Out:
- ; AX - GUS frequency number
- ; EAX high word - ?
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gus_get_freq:
- push edx
- xor edx,edx
- shl eax,10
- div dword ptr freqfactor
- pop edx
- ret
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Put sample data into GUS ram
- ; In:
- ; EBX - addx in GUS ram to put to
- ; ECX - length in bytes to put
- ; EDX -> sample data to put
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gus_put_data:
- push eax ebx ecx dx esi
- mov esi,edx
- mov dx,gusport104
- putdatal0:
- dec edx
- mov al,44h
- mov port103val,al
- out dx,al
- add dl,2
- shld eax,ebx,16
- out dx,al
- sub dl,2
- mov al,43h
- mov port103val,al
- out dx,al
- inc edx
- putdatal1:
- mov ax,bx
- out dx,ax
- add dl,3
- outsb
- sub dl,3
- inc bx
- loopnz putdatal1
- jecxz short putdatad
- add ebx,10000h
- jmp putdatal0
- putdatad:
- pop esi dx ecx ebx eax
- ret
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Get sample data from GUS ram
- ; In:
- ; EBX - addx in GUS ram to get from
- ; ECX - length in bytes to get
- ; EDX -> buffer for sample data
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gus_get_data:
- push eax ebx ecx dx edi
- mov edi,edx
- mov dx,gusport104
- getdatal0:
- dec edx
- mov al,44h
- mov port103val,al
- out dx,al
- add dl,2
- shld eax,ebx,16
- out dx,al
- sub dl,2
- mov al,43h
- mov port103val,al
- out dx,al
- inc edx
- getdatal1:
- mov ax,bx
- out dx,ax
- add dl,3
- insb
- sub dl,3
- inc bx
- loopnz getdatal1
- jecxz short getdatad
- add ebx,10000h
- jmp getdatal0
- getdatad:
- pop edi dx ecx ebx eax
- ret
-
- code32 ends
- end
-
-